﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.NetworkInformation;
using Wala.Connection.Constants;
using Wala.Connection.Argument;
using System.Threading.Tasks;

namespace Wala.Connection.ComConnections
{
    public class NetworkChecker
    {
        Task checkThread;
        bool running = true;
        //ReadWriteThread readWriteThread;
        ConnectionManagement conn = ConnectionManagement.Instance;
        NetworkAddressChangedEventHandler networdAddressChanged;
        public object checkLock = new object();
        private static string host;

        public static string Host
        {
            get { return NetworkChecker.host; }
            set { NetworkChecker.host = value; }
        }

        public bool Running
        {
            get { return running; }
            set { running = value; }
        }
        public NetworkChecker()
        {
            networdAddressChanged = new NetworkAddressChangedEventHandler(NetWorkChanged);
            NetworkChange.NetworkAddressChanged += networdAddressChanged;
            Task.Run(() => CheckNetwork());
        }

        private void NetWorkChanged(object sender, EventArgs e)
        {
            conn.PulseChecker();
            int i = 0;
        }

        //public void Close()
        //{
        //    running = false;
        //    if (readWriteThread != null)
        //        readWriteThread.Close();
        //    NetworkChange.NetworkAddressChanged -= networdAddressChanged;
        //    checkThread.Abort();
        //    checkThread.Join();
        //}

        //public void StopSocket()
        //{
        //    if (readWriteThread != null)
        //        readWriteThread.Close();
        //}

        //public void StartSocket()
        //{
        //    readWriteThread = new ReadWriteThread();
        //}

        private async Task CheckNetwork()
        {
            while (running)
            {
                lock (checkLock)
                {
                    bool available = Check();

                    switch (conn.State)
                    {
                        case ConnectionManagement.ConnectionState.DISCONNECTED:
                            if (available)
                            {
                                conn.NotifyUI(new NotifyEventArgs(EventConstants.HAS_NETWORK));
                                Monitor.Wait(checkLock);
                            }
                            else
                            {
                                Monitor.Wait(checkLock, 3000);
                            }
                            break;
                        case ConnectionManagement.ConnectionState.CONNECTING:
                            if (available)
                            {
                                Monitor.Wait(checkLock);
                            }
                            else
                            {
                                conn.NotifyUI(new NotifyEventArgs(EventConstants.CONNECT_FAIL));
                            }
                            break;
                        case ConnectionManagement.ConnectionState.CONNECTED:
                            if (!available)
                            {

                                conn.NotifyUI(new NotifyEventArgs(EventConstants.RET_LOST_CONNECTION));
                                //Monitor.Wait(checkLock);
                            }
                            else
                            {
                                Monitor.Wait(checkLock, 30000);
                            }
                            break;
                        case ConnectionManagement.ConnectionState.LOST_CONNECTION:
                            if (available)
                            {
                                conn.NotifyUI(new NotifyEventArgs(EventConstants.HAS_NETWORK));
                                Monitor.Wait(checkLock);
                            }
                            else
                            {
                                Monitor.Wait(checkLock, 3000);
                            }
                            break;
                    }

                    #region
                    //if (readWriteThread != null && readWriteThread.Running == true)
                    //{
                    //    conn.NotifyUI(new NotifyEventArgs(EventConstants.RET_LOST_CONNECTION));  
                    //}
                    //else
                    //{
                    //    conn.NotifyUI(new NotifyEventArgs(EventConstants.RET_SOCKET_CONNECT_ERR));
                    //}
                    #endregion
                }
                //Thread.Sleep(30000);
            }
        }

        public static bool Check()
        {
            return NetworkInterface.GetIsNetworkAvailable();
        }

        //public static bool Check(string host)
        //{
        //    bool result = false;
        //    Ping p = new Ping();
        //    try
        //    {
        //        PingReply reply = p.Send(host, 3000);
        //        if (reply.Status == IPStatus.Success)
        //            return true;
        //    }
        //    catch
        //    {
        //    }
        //    return result;
        //}
    }
}